package DCSource.Archive;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

import DCSource.Statereader;
import DCSource.filer;

public class Zipfile {
	private ZipFile zip;
	private File tosave;
	private boolean canWork;
	public Zipfile(File file){
		this.tosave = file;
		try {
			zip = new ZipFile(file);
			canWork=true;
		} catch (Exception e) {
			canWork=false;
		}
	}
	public Zipfile(String file){
		this.tosave = new File(file);
		try {
			zip = new ZipFile(file);
			canWork=true;
		} catch (Exception e) {
			canWork=false;
		}
	}
	public void createClearZip(String file){
		ZipOutputStream zipOut  = null;
		try
		{
		   zipOut  = new ZipOutputStream( new FileOutputStream(file) ) ;
		   zipOut.close();
		}
		catch(IOException ex)
		{
		  
		}
	}
	public boolean exist(String name){
		if (canWork){
			Enumeration enu = zip.entries();
			while (enu.hasMoreElements())
			{
			   ZipEntry zipEntry = (ZipEntry)enu.nextElement();
			   if (zipEntry.getName().equals(name)){
				   return true;
			   }
			}
		}
		return false;
	}
	public boolean CanWork(){
		return canWork;
	}
	public FileInformation[] getFiles(){
		if (canWork){
			ArrayList<FileInformation> list = new ArrayList<FileInformation>();
			Enumeration enu = zip.entries();
			while (enu.hasMoreElements())
			{
			   ZipEntry zipEntry = (ZipEntry)enu.nextElement();
			   list.add(new FileInformation(zipEntry.getName(),zipEntry.getTime(),zipEntry.getSize(),zipEntry.getCompressedSize(), !zipEntry.isDirectory()));
			}
			return list.toArray(new FileInformation[list.size()]);
		}
		return null;
	}
	public FileInformation getFile(String Filename){
		if (canWork){
			FileInformation file = null;
			Enumeration enu = zip.entries();
			while (enu.hasMoreElements()){
				ZipEntry zipEntry = (ZipEntry) enu.nextElement();
				if (zipEntry.getName().equals(Filename)){
					file = new FileInformation(zipEntry.getName(),zipEntry.getTime(),zipEntry.getSize(),zipEntry.getCompressedSize(), !zipEntry.isDirectory());
				}
			}
			return file;
		}
		return null;
	}
	public int getCount(){
		if (canWork){
			return zip.size();
		}
		return -1;
	}
	public String getComment(){
		if (canWork){
			return zip.getComment();
		}
		return null;
	}
	public int getSize(){
		if (canWork){
			int size = -1;
			FileInputStream t;
			try {
				t = new FileInputStream(tosave);
				size = t.available();
				t.close();
			} catch (Exception e) {
				
			}
			return size;
		}
		return -1;
	}
	public byte[] getBytesOf(String filename){
		if (canWork){
			byte[] re = new byte[]{};
			Enumeration enu = zip.entries();
			while (enu.hasMoreElements()){
				ZipEntry zipEntry = (ZipEntry) enu.nextElement();
				if (zipEntry.getName().equals(filename)){
					try {
						BufferedInputStream bis = new BufferedInputStream(zip.getInputStream(zipEntry));
						re = new byte[bis.available()];
						bis.read(re);
					} catch (Exception e) {
						
					}
				}
			}
			return re;
		}
		return null;
	}
	public String ReadText(String filename){
		return new String(getBytesOf(filename));
	}
	public void packFiles(String[] files,int Level){
		if (canWork){
			try{
				ArrayList<toZipFile> list = new ArrayList<toZipFile>();
				for (int I=0;I<files.length;I++){
					File m = new File(files[I]);
					if (m.exists()){
						filer reader = new filer();
						list.add(new toZipFile(m.getName(),reader.loadFile(m.getAbsolutePath())));
					}
				}
				ZipOutputStream zip = new ZipOutputStream(new FileOutputStream(tosave));
				zip.setLevel(Level);
				for (int I=0;I<list.size();I++){
					zip.putNextEntry(new ZipEntry(list.get(I).getName()));
					zip.write(list.get(I).getSRC());
					zip.closeEntry();
				}
				zip.close();
			}catch(Exception err){}
		}
	}
	public void packFiles(String[] files,int Level,String comment){
		if (canWork){
			try{
				ArrayList<toZipFile> list = new ArrayList<toZipFile>();
				for (int I=0;I<files.length;I++){
					File m = new File(files[I]);
					if (m.exists()){
						filer reader = new filer();
						list.add(new toZipFile(m.getName(),reader.loadFile(m.getAbsolutePath())));
					}
				}
				ZipOutputStream zip = new ZipOutputStream(new FileOutputStream(tosave));
				zip.setLevel(Level);
				zip.setComment(comment);
				for (int I=0;I<list.size();I++){
					zip.putNextEntry(new ZipEntry(list.get(I).getName()));
					zip.write(list.get(I).getSRC());
					zip.closeEntry();
				}
				zip.close();
			}catch(Exception err){}
		}
	}
	public void packFiles(ArrayList<toZipFile> list,int Level,String comment){
		if (canWork){
			try{
				ZipOutputStream zip = new ZipOutputStream(new FileOutputStream(tosave));
				zip.setLevel(Level);
				zip.setComment(comment);
				for (int I=0;I<list.size();I++){
					zip.putNextEntry(new ZipEntry(list.get(I).getName()));
					zip.write(list.get(I).getSRC());
					zip.closeEntry();
				}
				zip.close();
			}catch(Exception err){}
		}
	}
	public void packFiles(ArrayList<toZipFile> list,int Level){
		if (canWork){
			try{
				ZipOutputStream zip = new ZipOutputStream(new FileOutputStream(tosave));
				zip.setLevel(Level);
				for (int I=0;I<list.size();I++){
					zip.putNextEntry(new ZipEntry(list.get(I).getName()));
					zip.write(list.get(I).getSRC());
					zip.closeEntry();
				}
				zip.close();
			}catch(Exception err){}
		}
	}
	public void dePack(String file,String toPath){
		if (canWork){
			try{
				BufferedOutputStream bos = null;
				BufferedInputStream bis = null;
				bis = new BufferedInputStream(zip.getInputStream(zip.getEntry(file)));
				byte[] buffer = null;
				int avail = bis.available();
				if ( avail>0 )
				{
					buffer = new byte[avail];
					bis.read(buffer, 0, avail);
				}
				bis.close();
				toPath = toPath.replace("\\", "/");
				if (toPath.endsWith("/")==false){
					toPath += "/";
				}
				File name = new File(zip.getEntry(file).getName());
				String fileName = toPath + name.getName();
				bos = new BufferedOutputStream(new FileOutputStream(fileName));
				if (buffer!=null){
					bos.write(buffer, 0, buffer.length);
				}
				bos.close();
			}catch(Exception err){
				
			}
		}
	}
	public void dePack(String toPath){
		if (canWork){
			try{
				BufferedOutputStream bos = null;
				BufferedInputStream bis = null;
				toPath = toPath.replace("\\", "/");
				if (toPath.endsWith("/")==false){
					toPath += "/";
				}
				Enumeration enu = zip.entries();
				while (enu.hasMoreElements())
				{
				   ZipEntry zipEntry = (ZipEntry)enu.nextElement() ;
				   bis = new BufferedInputStream(zip.getInputStream(zipEntry));
				   byte[] buffer = null;
				   int avail = bis.available();
				   if ( avail>0 )
				   {
					   buffer = new byte[avail];
					   bis.read(buffer, 0, avail);
				   }
				   bis.close();
				   if (zipEntry.getName().endsWith("/")){
					   new File(toPath + zipEntry.getName()).mkdir();
				   }else{
					   String fileName = toPath + zipEntry.getName();
					   bos = new BufferedOutputStream(new FileOutputStream(fileName));
					   if (buffer!=null){
						   bos.write(buffer, 0, buffer.length);
					   }
					   bos.close();
				   }
				}
			}catch(Exception err){
				
			}
		}
	}
	public void dePack(String toPath, boolean overwrite){
		if (canWork){
			try{
				toPath = toPath.replace("\\", "/");
				if (toPath.endsWith("/")==false){
					toPath += "/";
				}
				Enumeration enu = zip.entries();
				while (enu.hasMoreElements()){
					ZipEntry entry = (ZipEntry) enu.nextElement();
					if (entry.isDirectory()){
						File b = new File(toPath+entry.getName());
						b.mkdirs();
					}else{
						BufferedOutputStream streamer = new BufferedOutputStream(new FileOutputStream(toPath+entry.getName()));
						BufferedInputStream reader = new BufferedInputStream(zip.getInputStream(entry));
						while(reader.available()>0){
							int toread = 1024;
							if (toread>reader.available()){
								toread = reader.available();
							}
							byte[] chunk = new byte[toread];
							reader.read(chunk,0,toread);
							streamer.write(chunk);
						}
						reader.close();
						streamer.close();
					}
				}
			}catch(Exception err){}
		}
	}
	public ArrayList<toZipFile> dePack(){
		if (canWork){
			ArrayList<toZipFile> list = new ArrayList<toZipFile>();
			try{
				BufferedInputStream bis = null;
				Enumeration enu = zip.entries();
				while (enu.hasMoreElements())
				{
				   ZipEntry zipEntry = (ZipEntry)enu.nextElement() ;
				   bis = new BufferedInputStream(zip.getInputStream(zipEntry));
				   byte[] buffer = null;
				   int avail = bis.available();
				   if ( avail>0 )
				   {
					   buffer = new byte[avail];
					   bis.read(buffer, 0, avail);
				   }
				   bis.close();
				   if (buffer!=null){
					   list.add(new toZipFile(zipEntry.getName(),buffer));
				   }
				}
			}catch(Exception err){
				
			}
			return list;
		}
		return null;
	}
	public boolean refresh(){
		if (canWork){
			try {
				zip = new ZipFile(tosave);
				return true;
			} catch (Exception e) {
				return false;
			}
		}
		return false;
	}
	public boolean close(){
		if (canWork){
			try {
				zip.close();
				return true;
			} catch (IOException e) {
				return false;
			}
		}
		return false;
	}
}
